/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package chatserver;

import java.io.*;
import java.net.Socket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author tiphanie
 */
public class ConnectedClient extends Thread {

    Socket socket;
    OnlineUser onlineUser;
    private PrintWriter writeStringOnSocket;
    private BufferedReader readStringFromSocket;

    public ConnectedClient(Socket s) {
        try {
            this.socket = s;
            writeStringOnSocket = new PrintWriter(
                    new BufferedWriter(
                    new OutputStreamWriter(this.socket.getOutputStream())),
                    true);
            readStringFromSocket = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
        } catch (IOException ex) {
            Logger.getLogger(ConnectedClient.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    void setOnlineUser(OnlineUser newUser) {
        onlineUser = newUser;
        ChatServer.users.add(newUser);
    }

    Conversation setPeopleOnAConversation(int conversationId, String[] users) {
        Conversation conversation = new Conversation(conversationId, users);
        ChatServer.conversations.put(conversationId, conversation);
        return conversation;
    }

    boolean isLoggedIn() {
        return onlineUser != null;
    }

    public String readLine() {
        try {
            return readStringFromSocket.readLine();
        } catch (IOException ex) {
            Logger.getLogger(ConnectedClient.class.getName()).log(Level.SEVERE, null, ex);
            return "";
        }
    }

    synchronized void writeLine(String line) {
        writeStringOnSocket.println(line);
    }

    void quit() {
        System.out.println("removing user" + onlineUser.username);
        ChatServer.users.remove(onlineUser);
        for (Conversation conv : ChatServer.conversations.values()) {
            conv.removeUser(onlineUser);
        }
        try {
            socket.close();
        } catch (IOException ex) {
            Logger.getLogger(ConnectedClient.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void run() {
        try {
            while (socket.isConnected()) {
                String commandSequence = readLine();
                if (commandSequence == null) {
                    commandSequence = "quit";
                }
                System.out.println("command: " + commandSequence);
                int pos = commandSequence.indexOf(" ");
                String arguments = pos == -1 ? "" : commandSequence.substring(pos + 1);
                String command = pos == -1 ? commandSequence : commandSequence.substring(0, pos);
                try {
                    if (command.equals("usernameExists")) {
                        String username = arguments;
                        if (ChatServer.database.usernameExists(username)) {
                            writeLine("used");
                        } else {
                            writeLine("free");
                        }
                    } else if (command.equals("create")) {
                        String[] parts = arguments.split(" ");
                        String username = parts[0];
                        String password = parts[1];
                        String name = parts[2];
                        String email = parts[3];
                        try {
                            User user = null;
                            if ((ChatServer.database.usernameExists(username))) {
                                throw new RuntimeException("Tried to create, but Username already exists.");
                            } else {
                                user = new User(name, username, password, email);
                            }
                            if (ChatServer.database.createUser(user)) {
                                writeLine("success");
                            } else {
                                System.out.println("erreur lors de l'enregistrement du client");
                                writeLine("notCreated");
                            }
                        } catch (SQLException ex) {
                            Logger.getLogger(ConnectedClient.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    } else if (command.equals("login")) {
                        String[] parts = arguments.split(" ");
                        String username = parts[0];
                        String password = parts[1];
                        try {
                            User user;
                            if ((user = ChatServer.database.login(username, password)) != null) {
                                writeLine("loggedIn");
                                System.out.println(username + " is logged in now");
                                setOnlineUser(new OnlineUser(username, this, user));
                            } else {
                                writeLine("wrongCombination");
                                System.out.println(username + " try to logged in");
                            }
                        } catch (SQLException ex) {
                            Logger.getLogger(ConnectedClient.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    } else if (isLoggedIn()) {
                        if (command.equals("message")) {
                            int spacePos = arguments.indexOf(" ");
                            int conversation = Integer.parseInt(arguments.substring(0, spacePos));
                            String message = arguments.substring(spacePos + 1);
                            ChatServer.conversations.get(conversation).writeMessage(onlineUser, message);
                            ChatServer.database.createMessage(conversation, onlineUser.username, message);

                        } else if (command.equals("quit")) {
                            quit();
                            break;
                        } else if (command.equals("listusers")) {
                            String userdata;
                            for (int i = 0; i < ChatServer.users.size(); i++) {
                                User currentUser = ChatServer.users.get(i).user;
                                userdata = currentUser.getUsername() + " (" + currentUser.getRealname() + ")";
                                writeLine("userlist " + userdata);
                            }

                        } else if (command.equals("accept")) {
                            int conversation = Integer.parseInt(arguments);
                            ChatServer.conversations.get(conversation).accept(onlineUser);

                        } else if (command.equals("listconversations")) {
                            int conversationCount = 0;
                            ArrayList<HistoricConversation> conversations = ChatServer.database.getConversationList(onlineUser.username);
                            for (HistoricConversation conv : conversations) {
                                writeLine("conversationslist " + conv.id + " (" + conv.date + "): " + conv.joinUsernames());
                                conversationCount++;
                            }
                            if (conversationCount == 0) {
                                writeLine("There are no conversations.");
                            }
                        } else if (command.equals("leave")) {
                            if (!arguments.isEmpty()) {
                                int conversation = Integer.parseInt(arguments);
                                ChatServer.conversations.get(conversation).leave(onlineUser);
                                writeLine("You left conversation " + conversation);
                            }
                        } else if (command.equals("start")) {
                            String[] usernames = arguments.split(" ");
                            boolean containsInitiator = false;
                            for (int i = 0; i < usernames.length; i++) {
                                if (usernames[i].equals(onlineUser.username)) {
                                    containsInitiator = true;
                                    break;
                                }
                            }
                            if (!containsInitiator) {
                                usernames = (arguments + " " + onlineUser.username).split(" ");
                            }

                            if (ChatServer.checkUsernamesOnline(usernames)) {
                                int conversationId = ChatServer.database.createConversation();
                                Conversation conversation = setPeopleOnAConversation(conversationId, usernames);
                                conversation.sendInvite();
                                conversation.accept(onlineUser);
                                writeLine("youStarted " + conversationId);

                            } else {
                                writeLine("the people you entered are not connected");
                            }

                        } else if (command.equals("history")) {
                            if (!arguments.isEmpty()) {
                                int conversationId = Integer.parseInt(arguments);

                                ArrayList<Message> messages = ChatServer.database.getHistory(onlineUser.username, conversationId);
                                if (messages.size() > 0) {
                                    for (int i = 0; i < messages.size(); i++) {
                                        writeLine("history " + messages.get(i).getDate() + " " + messages.get(i).getConversationID() + " " + messages.get(i).getUsername() + " " + messages.get(i).getText());
                                    }
                                } else {
                                    writeLine("You cannot see this history.");
                                }
                            }
                        } else {
                            writeLine("Command Not Found");
                        }
                }
            }catch(Exception e){
             writeLine("Error processing command");
            }
        }
    }
    catch (Exception e) {
            //e.printStackTrace();
            quit();
    }
}
}
